home *** CD-ROM | disk | FTP | other *** search
- unit PcxClass;
- {*=====================================================================
- Classes: PCX_Reader
-
- File: PCXClass.pas
-
- Summary:
- PCXClass.pas contain a moreless useful PCX-viewer class, and some
- others to make it working. BitWise also needed (BitWiseClass.pas).
- It will work with the most widely distributed 256 or 24bit color
- pictures and the older 16 bit ones.
-
- Known issues are the possibly problems with true CGA pictures
- and the packed 16 bit ones (with 4 planes).
- Some coding solution surely will be like a stone-age way
- for professionals, but probably not for starter ones in the C#-world.
-
- This .NET-class was implemented by Endre I Simay according to
-
- ---------------------------------------------------------------------
- This file is submitted by:
-
- endresy@axelero.hu
- Endre I. Simay,
- Hungary
-
- THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- PARTICULAR PURPOSE.
- =====================================================================*}
-
- interface
- uses
- System.IO,
- bitwiseclass;
-
- type
- VideoModes = class // video modes
- public
- CGA4,
- CGA2,
- EGA,
- VGA,
- MCGA,
- MCGA2: byte;
- constructor Create;
- end;
-
- dword = UInt32;
-
- BITMAPFILEHEADER = record
- bfType: word;
- bfSize: dword;
- bfReserved1,
- bfReserved2: word;
- bfOffBits: dword;
- end; // Size=14
-
- BITMAPINFOHEADER = record
- biSize: dword;
- biWidth,
- biHeight: Int32;
- biPlanes,
- biBitCount: word;
- biCompression,
- biSizeImage: dword;
- biXPelsPerMeter,
- biYPelsPerMeter: Int32;
- biClrUsed,
- biClrImportant: dword;
- end; // Size=40
-
- PCX_Header = class
- public
- Manufacturer: byte; // Always 10 for PCX file
- Version: byte;
- {* 2 - old PCX - no palette (NOT used anymore),
- 3 - no palette,
- 4 - Microsoft Windows - no palette (only in
- old files, New Windows version USES 3),
- 5 - WITH palette *}
- Encoding: byte;
- {* 1 is PCX, it is possible that we may add
- additional encoding methods IN the future *}
- Bits_per_pixel: byte;
- {* Number of bits to represent a pixel
- (per plane) - 1, 2, 4, or 8 *}
- Xmin: Int16; // Image window dimensions (inclusive)
- Ymin: Int16; // Xmin, Ymin are usually zero (not always)
- Xmax: Int16;
- Ymax: Int16;
- Hdpi: Int16; // Resolution of image (dots per inch)
- Vdpi: Int16; // Set to scanner resolution - 300 is default
- ColorMap: array[0..15, 0..2] of byte;
- {* RGB palette data (16 colors or less)
- 256 color palette is appended to END OF FILE *}
- Reserved: byte;
- {* (used to contain video mode)
- now it is ignored - just set to zero *}
- Nplanes: byte; // Number of planes
- Bytes_per_line_per_plane,
- {* Number of bytes to allocate
- for a scanline plane.
- MUST be an an EVEN number!
- DO NOT calculate from Xmax-Xmin! *}
- PaletteInfo: word;
- {* 1 = black & white or color image,
- 2 = grayscale image - ignored IN PB4, PB4+
- palette must also be set to shades of gray! *}
- HscreenSize: Int16; // added for PC Paintbrush IV Plus ver 1.0,
- VscreenSize: Int16; // PC Paintbrush IV ver 1.02 (and later)
- Filler: array[0..53] of byte; // Set to zeros but mainly indifferent paddings to 128 byte
-
- constructor Create;
- end;
-
- PCX_Reader = class
- private
- PictureMode: Int16;
- RealWidth,
- RealHeight,
- Error,
- Index: integer;
- data: byte;
- bytes_per_line: word;
- video: VideoModes;
- PCXheader: PCX_Header;
- PCXStream: System.IO.StreamReader;
- breader: System.IO.BinaryReader;
- bwrite: System.IO.BinaryWriter;
- ms: MemoryStream;
- Fbitmapfileheader: BITMAPFILEHEADER;
- Fbitmapinfoheader: BITMAPINFOHEADER;
- errors: array[0..6] of string;
- procedure PCX_Reader_Init;
- procedure FromFileToStream(FilePath: string; IStream: Stream);
- procedure FromStreamToStream(IStream: Stream);
- procedure FillBitmapStructs;
- procedure ReadPalettes(IStream: Stream);
- procedure Read256palette(IStream: Stream); // Read in a 256 color palette at end of PCX file
- procedure ReadMCGA2palette(IStream: Stream); // Read in a 24b color PCX file
- procedure ReadVGA16palette(IStream: Stream); // Read in a 16 color PCX file
-
- strict protected
- procedure Dispose(Disposing: Boolean);
-
- public
- constructor Create;
- function PCX_ErrorString: string;
- function PCX_ErrorNumber: integer;
- function FromStream(Source: Stream): Stream;
- function FromFile(FilePath: string): Stream;
- end;
-
- implementation
- const
- PCX_errors: array[0..6] of string = (
- 'No problems.',
- 'Problem with opening the sourcefile.',
- 'Problem to read the PCX-header.',
- 'Problem with initializing the BinaryReader.',
- 'Not a valid PCX-file for this decoder.',
- 'Problem with reading the palette.',
- 'Any problem with reading from or writing to a stream of the image.')
- ;
-
- constructor VideoModes.Create; // video modes
- begin
- inherited;
- CGA4 := $04;
- CGA2 := $06;
- EGA := $10;
- VGA := $12;
- MCGA := $13;
- MCGA2 := $15;
- end;
-
- constructor PCX_Header.Create;
- begin
- inherited;
- end;
-
- constructor PCX_Reader.Create;
- begin
- inherited;
- PCX_Reader_Init;
- end;
-
- procedure PCX_Reader.Dispose(Disposing: Boolean);
- begin
- if (disposing) then
- begin
- if (bwrite <> nil) then
- begin
- bwrite.Close();
- end;
- end;
- end;
-
- procedure PCX_Reader.PCX_Reader_Init;
- begin
- video := VideoModes.Create;
- PCXheader := PCX_Header.Create;
- PictureMode := 0;
- Error := 0;
- Index := 0;
- data := 0;
- bytes_per_line := 0;
- RealWidth := 0;
- RealHeight := 0;
- ms := MemoryStream.Create;
- bwrite := BinaryWriter.Create(ms);
- errors[0] := 'No problems.';
- errors[1] := 'Problem with opening the sourcefile.';
- errors[2] := 'Problem to read the PCX-header.';
- errors[3] := 'Problem with initializing the BinaryReader.';
- errors[4] := 'Not a valid PCX-file for this decoder.';
- errors[5] := 'Problem with reading the palette.';
- errors[6] := 'Any problem with reading from or writing to a stream of the image.';
- end;
-
- function PCX_Reader.PCX_ErrorString: string;
- begin
- Result := errors[Error];
- end;
-
- function PCX_Reader.PCX_ErrorNumber: integer;
- begin
- Result := Error;
- end;
-
-
- function PCX_Reader.FromStream(Source: Stream): Stream;
- var
- IStream: MemoryStream;
- begin
- IStream := MemoryStream.Create;
- PCXStream := StreamReader.Create(Source);
- FromStreamToStream(IStream);
- if (Error = 0) then
- begin
- Result := IStream;
- end
- else
- begin
- Result := nil;
- end;
- end;
-
- function PCX_Reader.FromFile(FilePath: string): Stream;
- var
- IStream: MemoryStream;
- begin
- IStream := MemoryStream.Create;
- PCXStream := StreamReader.Create(FilePath);
- FromStreamToStream(IStream);
- if (Error = 0) then
- begin
- Result := IStream;
- end
- else
- begin
- Result := nil;
- end;
- end;
-
- procedure PCX_Reader.FromFileToStream(FilePath: string; IStream: Stream);
-
- begin
- try
- PCXStream := StreamReader.Create(FilePath);
- FromStreamToStream(IStream);
- except
- Error := 1; //Problem with opening the sourcefile
- end;
- end;
-
- procedure PCX_Reader.FromStreamToStream(IStream: Stream);
- var
- i, j: integer;
- begin
- PCX_Reader_Init();
- try
- breader := BinaryReader.Create(PCXStream.BaseStream);
- try
- PCXheader.Manufacturer := breader.ReadByte();
- PCXheader.Version := breader.ReadByte();
- PCXheader.Encoding := breader.ReadByte();
- PCXheader.Bits_per_pixel := breader.ReadByte();
- PCXheader.Xmin := breader.ReadInt16();
- PCXheader.Ymin := breader.ReadInt16();
- PCXheader.Xmax := breader.ReadInt16();
- PCXheader.Ymax := breader.ReadInt16();
- PCXheader.Hdpi := breader.ReadInt16();
- PCXheader.Vdpi := breader.ReadInt16();
- for j := 0 to 15 do
- begin
- for i := 0 to 2 do
- begin
- PCXheader.ColorMap[j, i] := breader.ReadByte;
- end;
- end;
- PCXheader.Reserved := breader.ReadByte();
- PCXheader.Nplanes := breader.ReadByte();
- PCXheader.Bytes_per_line_per_plane := breader.ReadUInt16();
- PCXheader.PaletteInfo := breader.ReadUInt16();
- PCXheader.HscreenSize := breader.ReadInt16();
- PCXheader.VscreenSize := breader.ReadInt16();
- PCXheader.Filler := breader.ReadBytes(55);
- except
- Error := 2; //Problem to read the PCX-header
- end;
- except
- Error := 3; //Problem with initializing the BinaryReader
- end;
- if (Error = 0) then
- begin
- if ((PCXheader.Manufacturer <> 10) or (PCXheader.Encoding <> 1)) then
- begin
- Error := 4; //Not a valid PCX-file
- end;
- if ((PCXheader.Nplanes = 3) and (PCXheader.Bits_per_pixel = 8)) then
- begin
- PictureMode := video.MCGA2;
- end;
- if ((PCXheader.Nplanes = 4) and (PCXheader.Bits_per_pixel = 1)) then
- begin
- PictureMode := video.VGA;
- end;
-
- if ((PCXheader.Nplanes = 1) and (PCXheader.Bits_per_pixel = 4)) then
- begin
- Error := 4; //Not a valid PCX-file for this class
- {* Not implemented yet *}
- end;
-
- if (PCXheader.Nplanes = 1) then
- begin
- if (PCXheader.Bits_per_pixel = 1) then
- begin
- PictureMode := video.VGA;
- {* b/w PCX saved on Windows (e.g. from Paint Shop Pro)
- working with VGA-decoding, while true CGA2
- images may cause problem
- *}
- // Error := 4; //Not a valid PCX-file for this class
- end
- else
- begin
- if (PCXheader.Bits_per_pixel = 2) then
- begin
- PictureMode := video.CGA4;
- Error := 4; //Not a valid PCX-file for this class
- end
- else begin
- if (PCXheader.Bits_per_pixel = 8) then
- begin
- PictureMode := video.MCGA;
- if (PCXheader.Version <> 5) then
- begin
- Error := 4; //Not a valid PCX-file
- end;
- end;
- end;
- end;
- end;
- end;
- if (Error = 0) then
- begin
- bytes_per_line := word(PCXheader.Bytes_per_line_per_plane * PCXheader.Nplanes);
- RealWidth := PCXheader.Xmax - PCXheader.Xmin + 1;
- RealHeight := PCXheader.Ymax - PCXheader.Ymin + 1;
- FillBitmapStructs();
- ReadPalettes(PCXStream.BaseStream);
- end;
- if (breader <> nil) then
- begin
- breader.Close();
- end;
- if (PCXStream <> nil) then
- begin
- PCXStream.Close();
- end;
- if (Error = 0) then
- begin
- (MemoryStream(bwrite.BaseStream)).WriteTo(IStream);
- end
- else
- begin
- IStream.Close;
- end;
- end;
-
- procedure PCX_Reader.FillBitmapStructs;
- begin
- Fbitmapfileheader.bfType := word($4D42);
- Fbitmapfileheader.bfSize := UInt32((3 * 255) + 14 {*Sizeof(BitmapFileHeader)*}
- + 40 {* Sizeof(TBitmapInfoHeader) *}
- + ((RealHeight) * (RealWidth)));
- Fbitmapfileheader.bfReserved1 := 0;
- Fbitmapfileheader.bfReserved2 := 0;
- Fbitmapfileheader.bfOffBits := (4 * 256) + 14 {*Sizeof(BitmapFileHeader)*}
- + 40 {* Sizeof(TBitmapInfoHeader) *};
- Fbitmapinfoheader.biSize := UInt32(40);
- Fbitmapinfoheader.biWidth := Int32(RealWidth);
- Fbitmapinfoheader.biHeight := Int32(RealHeight);
- Fbitmapinfoheader.biPlanes := word(1); // biPlanes := 1; Arcane and rarely used
- Fbitmapinfoheader.biBitCount := word(8); //biBitCount := 8; Most widely occurring for PCX format
- Fbitmapinfoheader.biCompression := UInt32(0); // biCompression := BI_RGB; Not needed compressing for the laters
- Fbitmapinfoheader.biSizeImage := UInt32(0); //biSizeImage := 0; Valid since we are not compressing the image
- Fbitmapinfoheader.biXPelsPerMeter := Int32(143); //biXPelsPerMeter := 143; Rarely used (Windows not use) very arcane field
- Fbitmapinfoheader.biYPelsPerMeter := Int32(143); //biYPelsPerMeter := 143; Ditto
- Fbitmapinfoheader.biClrUsed := UInt32(0); //biClrUsed := 0; all colors are used
- Fbitmapinfoheader.biClrImportant := UInt32(0); //biClrImportant := 0; all colors are important
- end;
-
- procedure PCX_Reader.ReadPalettes(IStream: Stream);
- begin
- Error := 0;
- if ((PictureMode = video.MCGA) and (PCXheader.Version = 5)) then
- begin
- Read256palette(IStream);
- end;
- if (PictureMode = video.MCGA2) then
- begin
- ReadMCGA2palette(IStream);
- end;
- if (PictureMode = video.VGA) then
- begin
- ReadVGA16palette(IStream);
- end;
- end;
-
- procedure PCX_Reader.Read256palette(IStream: Stream); // Read in a 256 color palette at end of PCX file
- var
- bytes_in_line, dY, i, j, k: integer;
- count: word;
- Palette256: array[0..255, 0..2] of byte;
- lines: array of array of byte;
-
- begin
- IStream.Seek((IStream.Length) - 769, SeekOrigin(0));
- try
- if (IStream.ReadByte() = 12) then // read indicator byte
- begin
- for j := 0 to 255 do // read palette if there is one
- begin
- for i := 0 to 2 do
- begin
- Palette256[j, i] := byte(IStream.ReadByte());
- end;
- end;
- IStream.Seek(128, SeekOrigin(0)); /// go back to start of PCX data
- Error := 0;
- end
- else
- begin
- Error := 5; // no palette here...
- end;
- except
- Error := 5; //Problem with reading the palette
- end;
-
- if (Error = 0) then
- begin
- try
- bwrite.Write(Fbitmapfileheader.bfType);
- bwrite.Write(Fbitmapfileheader.bfSize);
- bwrite.Write(Fbitmapfileheader.bfReserved1);
- bwrite.Write(Fbitmapfileheader.bfReserved2);
- bwrite.Write(Fbitmapfileheader.bfOffBits);
- bwrite.Write(Fbitmapinfoheader.biSize);
- bwrite.Write(Fbitmapinfoheader.biWidth);
- bwrite.Write(Fbitmapinfoheader.biHeight);
- bwrite.Write(Fbitmapinfoheader.biPlanes);
- bwrite.Write(Fbitmapinfoheader.biBitCount);
- bwrite.Write(Fbitmapinfoheader.biCompression);
- bwrite.Write(Fbitmapinfoheader.biSizeImage);
- bwrite.Write(Fbitmapinfoheader.biXPelsPerMeter);
- bwrite.Write(Fbitmapinfoheader.biYPelsPerMeter);
- bwrite.Write(Fbitmapinfoheader.biClrUsed);
- bwrite.Write(Fbitmapinfoheader.biClrImportant);
- for i := 0 to 255 do
- begin // R, G, and B must be 0..63
- bwrite.Write(byte(Palette256[i, 2]));
- bwrite.Write(byte(Palette256[i, 1]));
- bwrite.Write(byte(Palette256[i, 0]));
- bwrite.Write(byte(0));
- end;
- Index := 0;
- bytes_in_line := RealWidth;
- dY := 4 - (bytes_in_line - (bytes_in_line div 4) * 4);
- if (dY = 4) then
- begin
- dY := 0;
- end;
- bytes_in_line := bytes_in_line + dY;
- SetLength(lines, RealHeight, bytes_in_line);
- for i := 0 to RealHeight - 1 do
- begin
- if (Index <> 0) then
- begin
- for j := 0 to Index - 1 do
- begin
- lines[i, j] := data; // fills a contiguous block
- end;
- end;
- while (Index < bytes_per_line) do // read 1 line of data (all planes)
- begin
- data := byte(IStream.ReadByte);
- if (byte(data and byte($C0)) = byte($C0)) then
- begin
- count := word(byte(data and byte($3F)));
- data := byte(IStream.ReadByte);
- for j := 0 to count - 1 do
- begin
- lines[i, Index + j] := data; // fills a contiguous block
- end;
- Inc(Index, count);
- end
- else
- begin
- lines[i, Index] := data;
- Inc(Index);
- end;
- end;
- Index := Index - bytes_per_line;
- end;
- for k := RealHeight - 1 downto 0 do
- begin
- for i := 0 to bytes_in_line - 1 do
- begin
- bwrite.Write(byte(lines[k, i]));
- end;
- end;
- except
- Error := 6; // Any problem with reading from or writing to a stream of the image
- end;
-
- end;
- end;
-
- procedure PCX_Reader.ReadMCGA2palette(IStream: Stream); // Read in a 24b color PCX file
- var
- bytes_in_line, dY, i, j, k, L, x: integer;
- count: word;
- lines: array of array of byte;
- line: array of byte;
- begin
- IStream.Seek(128, SeekOrigin(0)); /// guaranted go to start of PCX data
- bytes_in_line := 3 * (RealWidth);
- dY := 4 - (bytes_in_line - (bytes_in_line div 4) * 4);
-
- if (dY = 4) then
- begin
- dY := 0;
- end;
- bytes_in_line := bytes_in_line + dY;
-
- if (Error = 0) then
- begin
- try
- Fbitmapfileheader.bfSize := UInt32((3 * 15) + 14 {*Sizeof(BitmapFileHeader)*}
- + 40 {* Sizeof(TBitmapInfoHeader) *}
- + ((RealHeight) * (RealWidth) * 3));
- Fbitmapfileheader.bfOffBits := 14 {*Sizeof(BitmapFileHeader)*}
- + 40 {* Sizeof(TBitmapInfoHeader) *};
- Fbitmapinfoheader.biBitCount := word(24);
- bwrite.Write(Fbitmapfileheader.bfType);
- bwrite.Write(Fbitmapfileheader.bfSize);
- bwrite.Write(Fbitmapfileheader.bfReserved1);
- bwrite.Write(Fbitmapfileheader.bfReserved2);
- bwrite.Write(Fbitmapfileheader.bfOffBits);
- bwrite.Write(Fbitmapinfoheader.biSize);
- bwrite.Write(Fbitmapinfoheader.biWidth);
- bwrite.Write(Fbitmapinfoheader.biHeight);
- bwrite.Write(Fbitmapinfoheader.biPlanes);
- bwrite.Write(Fbitmapinfoheader.biBitCount);
- bwrite.Write(Fbitmapinfoheader.biCompression);
- bwrite.Write(Fbitmapinfoheader.biSizeImage);
- bwrite.Write(Fbitmapinfoheader.biXPelsPerMeter);
- bwrite.Write(Fbitmapinfoheader.biYPelsPerMeter);
- bwrite.Write(Fbitmapinfoheader.biClrUsed);
- bwrite.Write(Fbitmapinfoheader.biClrImportant);
-
- Index := 0;
- SetLength(lines, RealHeight, bytes_in_line * 3);
- SetLength(line, bytes_in_line * 3);
- for i := 0 to RealHeight - 1 do
- begin
- if (Index <> 0) then
- begin
- for j := 0 to Index - 1 do
- begin
- line[j] := data; // fills a contiguous block
- end;
- end;
- while (Index < bytes_per_line) do // read 1 line of data (all planes)
- begin
- data := byte(IStream.ReadByte);
- if (byte(data and byte($C0)) = byte($C0)) then
- begin
- count := word(byte(data and byte($3F)));
- data := byte(IStream.ReadByte);
- for j := 0 to count - 1 do
- begin
- line[Index + j] := data; // fills a contiguous block
- end;
- Inc(Index, count);
- end
- else
- begin
- line[Index] := data;
- Inc(Index);
- end;
- end;
- Index := Index - bytes_per_line;
- x := 0;
- for L := 0 to PCXheader.Bytes_per_line_per_plane - 1 do
- begin
- lines[i, x + 2] := line[L];
- lines[i, x + 1] := line[L + PCXheader.Bytes_per_line_per_plane];
- lines[i, x] := line[L + 2 * PCXheader.Bytes_per_line_per_plane];
- lines[i, x + 3] := 0;
- x := x + 3;
- end;
- end;
- for k := RealHeight - 1 downto 0 do
- begin
- for i := 0 to bytes_in_line - 1 do
- begin
- bwrite.Write(byte(lines[k, i]));
- end;
- end;
- except
- Error := 6; // Any problem with reading from or writing to a stream of the image
- end;
-
- end;
-
- end;
-
- procedure PCX_Reader.ReadVGA16palette(IStream: Stream); // Read in a 16 color PCX file
- var
- bitwise: ByteBitWise;
- c: byte;
- bytes_in_line, dY, i, j, k, L, x, kmax: integer;
- count: word;
- lines: array of array of byte;
- line: array of byte;
-
- begin
- bitwise := ByteBitWise.Create;
-
- IStream.Seek(128, SeekOrigin(0)); /// guaranted go to start of PCX data
- if (Error = 0) then
- begin
- try
- Fbitmapfileheader.bfSize := UInt32((3 * 15) + 14 {*Sizeof(BitmapFileHeader)*}
- + 40 {* Sizeof(TBitmapInfoHeader) *}
- + ((RealHeight) * (RealWidth)));
- Fbitmapfileheader.bfOffBits := (4 * 16) + 14 {*Sizeof(BitmapFileHeader)*}
- + 40 {* Sizeof(TBitmapInfoHeader) *};
- Fbitmapinfoheader.biBitCount := word(4); //biBitCount := 24;
- bwrite.Write(Fbitmapfileheader.bfType);
- bwrite.Write(Fbitmapfileheader.bfSize);
- bwrite.Write(Fbitmapfileheader.bfReserved1);
- bwrite.Write(Fbitmapfileheader.bfReserved2);
- bwrite.Write(Fbitmapfileheader.bfOffBits);
- bwrite.Write(Fbitmapinfoheader.biSize);
- bwrite.Write(Fbitmapinfoheader.biWidth);
- bwrite.Write(Fbitmapinfoheader.biHeight);
- bwrite.Write(Fbitmapinfoheader.biPlanes);
- bwrite.Write(Fbitmapinfoheader.biBitCount);
- bwrite.Write(Fbitmapinfoheader.biCompression);
- bwrite.Write(Fbitmapinfoheader.biSizeImage);
- bwrite.Write(Fbitmapinfoheader.biXPelsPerMeter);
- bwrite.Write(Fbitmapinfoheader.biYPelsPerMeter);
- bwrite.Write(Fbitmapinfoheader.biClrUsed);
- bwrite.Write(Fbitmapinfoheader.biClrImportant);
- for L := 0 to 15 do // R, G, and B must be 0..63
- begin
- bwrite.Write(byte(PCXheader.ColorMap[L, 2]));
- bwrite.Write(byte(PCXheader.ColorMap[L, 1]));
- bwrite.Write(byte(PCXheader.ColorMap[L, 0]));
- bwrite.Write(byte(0));
- end;
- kmax := PCXheader.Ymin + PCXheader.Ymax;
- x := 0;
- Index := 0;
- bytes_in_line := RealWidth div 2;
- dY := 4 - (bytes_in_line - (bytes_in_line div 4) * 4);
- if (dY = 4) then
- begin
- dY := 0;
- end;
- bytes_in_line := bytes_in_line + dY;
- SetLength(lines, RealHeight, bytes_in_line * 2);
- SetLength(line, bytes_in_line * 2);
- for i := 0 to RealHeight - 1 do
- begin
- if (Index = 0) then
- begin
- for j := 0 to Index - 1 do
- begin
- line[j] := data; // fills a contiguous block
- end;
- end;
- while (Index < bytes_per_line) do // read 1 line of data (all planes)
- begin
- data := byte(IStream.ReadByte);
- if (byte(data and byte($C0)) = byte($C0)) then
- begin
- count := word(byte(data and byte($3F)));
- data := byte(IStream.ReadByte);
- for j := 0 to count - 1 do
- begin
- line[Index + j] := data; // fills a contiguous block
- end;
- Inc(Index, count);
- end
- else
- begin
- line[Index] := data;
- Inc(Index);
- end;
- end;
- Index := Index - bytes_per_line;
- for dY := 0 to (bytes_in_line * 2) - 1 do
- begin
- lines[i, dY] := 0;
- end;
- x := 0;
- for dY := 0 to PCXheader.Nplanes - 1 do
- begin
- for j := 0 to PCXheader.Bytes_per_line_per_plane - 1 do
- begin
- c := line[x];
- Inc(x);
- for k := 0 to 7 do
- begin
- if ((byte(c) and bitwise.byteshr(128, byte(k))) > 0) then
- begin
- lines[i, (j * 8) + k] := byte(lines[i, (j * 8) + k] or bitwise.byteshl(1, byte(dY)));
- end;
- end;
- end;
- end;
- for dY := 0 to (bytes_in_line * 2) - 1 do
- begin
- line[dY] := lines[i, dY];
- end;
- dY := (-1);
- x := (-1);
- while (x < (PCXheader.Xmax - PCXheader.Xmin)) do
- begin
- Inc(dY);
- Inc(x);
- lines[i, dY] := byte(bitwise.byteshl(line[x], 4) xor line[x + 1] and $0F);
- Inc(x);
- end;
- end;
- for k := RealHeight - 1 downto 0 do
- begin
- for i := 0 to bytes_in_line - 1 do
- begin
- bwrite.Write(byte(lines[k, i]));
- end;
- end;
- except
- Error := 6; // Any problem with reading from or writing to a stream of the image
- end;
- end;
- end;
-
- end.
-